class AsyncSeriesWaterfallHook {
  constructor () {
    this.tasks = []
  }

  tap (name, task) {
    this.tasks.push(task)
  }

  tapPromise (name, task) {
    this.tasks.push(task)
  }

  promise (...args) {
    const [ first, ...other ] = this.tasks

    return other.reduce(
      (prev, next) => prev.then((data) => next(data)), first(...args)
    )
  }
}

let hook2 = new AsyncSeriesWaterfallHook(['name promise'])

hook2.tapPromise('react', (data) => {
  return new Promise(((resolve, reject) => {
    setTimeout(() => {
      console.log('promise: react', data)
      resolve('firstArguments')
    }, 1000)
  }))
})

hook2.tapPromise('node', (data) => {
  return new Promise(((resolve, reject) => {
    setTimeout(() => {
      console.log('promise: node', data)
      resolve('secondArguments')
    }, 1000)
  }))
})

hook2.promise('xyf').then((data) => {
  console.log('promise: end', data)
})

